package com.ccys.common.third.payPal;





import com.ccys.common.enums.CodeEnum;
import com.ccys.common.third.payPal.config.*;
import com.ccys.common.util.JedisUtil;
import com.ccys.common.util.StringUtil;
import com.paypal.api.payments.*;
import com.paypal.base.rest.APIContext;
import com.paypal.base.rest.OAuthTokenCredential;
import com.paypal.base.rest.PayPalRESTException;

import lombok.extern.slf4j.Slf4j;

import org.springframework.context.annotation.DependsOn;
import org.springframework.stereotype.Component;
import org.springframework.test.context.ContextConfiguration;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

   /**
    * PayPal 支付
    * @author Administrator
    * 参考地址 ：https://blog.csdn.net/Japhet_jiu/article/details/129922941
    * https://www.paypal.com/myaccount/transfer/homepage
    * https://developer.paypal.com/home
    * https://developer.paypal.com/tools/sandbox/
    * 登录到开发者网站
    * https://developer.paypal.com/dashboard/
    * 沙箱账号登录
    * https://www.sandbox.paypal.com/signin
    *
    * demo
    * https://gitee.com/J-LJJ/paypal-demo/blob/master/paypal-demo/pom.xml
    *
    * V2 版本参考  https://www.cnblogs.com/gun-a/p/17123592.html
    * @date     2024/3/5
    * @author   cloud fly
    */
@Slf4j
@Component
@ContextConfiguration(classes = {PayPalConstants.class})
@DependsOn({"payPalConstants"})
public class PayPalUtil {
       //@Autowired
       private static APIContext apiContext;

       /**
        * accessToken 官方有效期一小时  默认缓存50分钟
        */
       private static final Integer DEFAULT_CACHE_TOKEN_TIME = 50 * 60;

       //初始化 api
       static {
           apiContext = new APIContext(PayPalConstants.clientId, PayPalConstants.clientSecret, PayPalConstants.mode);
       }

       PayPalUtil(){

       }


       /**
     *
     * @param total 支付金额
     * @param currency 支付货币（默认  "USD" 美元，）
     * @param method 付款方式（性用卡 credit_card, paypal）
     * @param intent 付款目的 （sale, authorize, order）
     * @param description 付款描述
     * @param cancelUrl 取消回调地址
     * @param successUrl 支付成功回调地址
     * @return
     * @throws PayPalRESTException
     */
    public static  Payment createPayment(BigDecimal total, String currency, PaypalPaymentMethod method, PaypalPaymentIntent intent,
                                 String description, String cancelUrl, String successUrl) throws PayPalRESTException {
        Amount amount = new Amount();
        if(StringUtil.isEmpty(currency)) {
            //默认美元
            currency = PaypalCurrency.UNITED_STATES_DOLLAR.getCode();
        }
        amount.setCurrency(currency);
        amount.setTotal(String.format("%.2f", total));

        Transaction transaction = new Transaction();
        transaction.setDescription(description);
        transaction.setAmount(amount);

        List<Transaction> transactions = new ArrayList<>();
        transactions.add(transaction);

        Payer payer = new Payer();
        payer.setPaymentMethod(method.toString());

        Payment payment = new Payment();
        payment.setIntent(intent.toString());
        payment.setPayer(payer);
        payment.setTransactions(transactions);
        RedirectUrls redirectUrls = new RedirectUrls();
        redirectUrls.setCancelUrl(cancelUrl);
        redirectUrls.setReturnUrl(successUrl);
        payment.setRedirectUrls(redirectUrls);

        return payment.create(apiContext);
    }


       /**
        * @description 退款
        * @date     2024/3/6
        * @author   cloud fly
        */
       public static PaypalRefundReturn refundSale(PaypalRefundRequest request) {

           //APIContext apiContext = new APIContext(config.getClientId(), config.getClientSecret(), config.getEndpointMode());

           // ###Sale
           // A sale transaction.
           // Create a Sale object with the
           // given sale transaction id.

           // ###Refund
           // A refund transaction.
           // Use the amount to create
           // a refund object
           RefundRequest refund = new RefundRequest();
           // ###Amount
           // Create an Amount object to
           // represent the amount to be
           // refunded. Create the refund object, if the refund is partial
           Amount amount = new Amount();
           amount.setCurrency(request.getCurrency());
           amount.setTotal(request.getAmount().toString());
           refund.setAmount(amount);
           refund.setReason(request.getReason());


           try {
               if(request.getSaleId() == null) {
                   //注意这段代码，获取saleId
                   Payment payment = Payment.get(apiContext, request.getTradeNo());
                   Transaction transaction = payment.getTransactions().get(0);
                   if(transaction != null && transaction.getRelatedResources() != null && !transaction.getRelatedResources().isEmpty()) {
                       RelatedResources resources = transaction.getRelatedResources().get(0);
                       String id = resources.getSale().getId();
                       request.setSaleId(id);
                   }

               }

               // ### Api Context
               // Pass in a `ApiContext` object to authenticate
               // the call and to send a unique request id
               // (that ensures idempotency). The SDK generates
               // a request id if you do not pass one explicitly.

               // Refund by posting to the APIService
               // using a valid AccessToken
               Sale sale = new Sale();
               sale.setId(request.getSaleId());
               DetailedRefund res = sale.refund(apiContext, refund);
               PaypalRefundReturn r = new PaypalRefundReturn();
               r.setState(res.getState());
               r.setAmount(res.getAmount().getTotal());
               r.setCurrency(res.getAmount().getCurrency());
               return r;
           } catch (PayPalRESTException e) {
               throw new IllegalStateException("failed to refund saleId=" + request.getTradeNo(), e);
           }
       }


          /**
           * @description 查询支付订单信息
           * @param paymentId  订单号
           * @date     2024/3/6
           * @author   cloud fly
           */
       public static Payment  getPayment(String paymentId) {
        // 根据支付ID查询支付状态
           try {
               Payment payment = Payment.get(apiContext, paymentId);
               String paymentStatus = payment.getState();
               System.out.println("Payment Status: " + paymentStatus);
               return payment;
           } catch (PayPalRESTException e) {
               System.err.println(e.getDetails());
           }
           return null;
       }


          /**
           * @description 获取paypal访问token
           * @date     2024/3/6
           * @author   cloud fly
           */
       public static String  getAccessToken() {
           // 获取AccessToken
           String accessToken = "";
           try {
               accessToken = JedisUtil.get("accessTokenPayPal", CodeEnum.REDIS_THIRD.codeOf());
               if(StringUtil.isEmpty(accessToken)) {
                   accessToken = new OAuthTokenCredential(PayPalConstants.clientId, PayPalConstants.clientSecret,PaypalConfig.paypalSdkConfig()).getAccessToken();
                   JedisUtil.setex("accessTokenPayPal", PayPalUtil.DEFAULT_CACHE_TOKEN_TIME, accessToken, CodeEnum.REDIS_THIRD.codeOf());
               }
           } catch (Exception e) {
               System.err.println("Failed to get Access Token: " + e.getMessage());
           }
           return accessToken;
       }


   }
